package com.yserp.project.erp.store.outorder.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yserp.common.exception.BusinessException;
import com.yserp.common.utils.DateUtils;
import com.yserp.common.utils.StringUtils;
import com.yserp.common.utils.bean.BeanUtils;
import com.yserp.common.utils.mybatis.MybatisPlusUtil;
import com.yserp.common.utils.security.ShiroUtils;
import com.yserp.common.utils.text.Convert;
import com.yserp.project.erp.common.enums.CheckStatusEnums;
import com.yserp.project.erp.common.enums.DeliverStatusEnums;
import com.yserp.project.erp.common.enums.OrderEnums;
import com.yserp.project.erp.common.enums.OutOrderTypeEnums;
import com.yserp.project.erp.common.util.DateSearchUtils;
import com.yserp.project.erp.order.productorder.domain.ProductionOrder;
import com.yserp.project.erp.order.productorder.domain.ProductionOrderItem;
import com.yserp.project.erp.order.productorder.service.IProductionOrderItemService;
import com.yserp.project.erp.order.productorder.service.IProductionOrderService;
import com.yserp.project.erp.order.saleorder.domain.ErpSaleOrder;
import com.yserp.project.erp.order.saleorder.domain.ErpSaleOrderItem;
import com.yserp.project.erp.order.saleorder.service.IErpSaleOrderItemService;
import com.yserp.project.erp.order.saleorder.service.IErpSaleOrderService;
import com.yserp.project.erp.record.checkorderlog.domain.CheckOrderLog;
import com.yserp.project.erp.record.checkorderlog.service.ICheckOrderLogService;
import com.yserp.project.erp.store.outorder.domain.OutOrder;
import com.yserp.project.erp.store.outorder.domain.OutOrderDto;
import com.yserp.project.erp.store.outorder.domain.OutOrderItem;
import com.yserp.project.erp.store.outorder.domain.OutOrderItemVo;
import com.yserp.project.erp.store.outorder.domain.OutOrderVo;
import com.yserp.project.erp.store.outorder.mapper.OutOrderMapper;
import com.yserp.project.erp.store.outorder.service.IOutOrderItemService;
import com.yserp.project.erp.store.outorder.service.IOutOrderService;
import com.yserp.project.erp.store.outstorelog.domain.StockOutLog;
import com.yserp.project.erp.store.stock.domain.Stock;
import com.yserp.project.erp.store.stock.service.IStockService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 商品出库单主Service业务层处理
 *
 * @author yserp
 * @date 2022-07-13
 */
@Service
public class OutOrderServiceImpl extends ServiceImpl<OutOrderMapper, OutOrder> implements IOutOrderService {
    @Resource
    private OutOrderMapper outOrderMapper;
    @Autowired
    private IOutOrderItemService outOrderItemService;
    @Autowired
    private ICheckOrderLogService checkOrderLogService;
    @Autowired
    private IStockService stockService;
    @Autowired
    private IErpSaleOrderService saleOrderService;
    @Autowired
    private IErpSaleOrderItemService saleOrderItemService;
    @Autowired
    private IProductionOrderItemService productionOrderItemService;
    @Autowired
    private IProductionOrderService productionOrderService;

    /**
     * 查询商品出库单主
     *
     * @param id 商品出库单主主键
     * @return 商品出库单主
     */
    @Override
    public OutOrderVo selectOutOrderById(Long id) {
        OutOrderVo outOrderVo = new OutOrderVo();
        OutOrder outOrder = outOrderMapper.selectById(id);
        if(null == outOrder){
            return outOrderVo;
        }
        outOrderVo.setOutOrder(outOrder);
        outOrderVo.setItems(outOrderItemService.selectOutOrderItemListByGoodIdAndWarehouseId(id,outOrder.getWarehouseId()));
        return outOrderVo;
    }

    /**
     * 查询商品出库单主列表
     *
     * @param outOrder 出库单
     * @return 商品出库单主
     */
    @Override
    public List<OutOrder> selectOutOrderList(OutOrder outOrder) {
        QueryWrapper<OutOrder> queryWrapper = new QueryWrapper<>();
        MybatisPlusUtil.notNullField(outOrder,queryWrapper);
        //对时间区间的处理
        DateSearchUtils.queryDateRange(outOrder,queryWrapper);
        return outOrderMapper.selectList(queryWrapper);
    }

    /**
     * 新增商品出库单主
     *
     * @param outOrderDto 出库单
     * @return 结果
     */
    @Override
    @Transactional
    public int insertOutOrder(OutOrderDto outOrderDto) {

        List<OutOrderItem> items = outOrderDto.getItems();
        if (CollectionUtils.isEmpty(items)) {
            throw new BusinessException("子表不能为空");
        }
        //验证单号是否存在
        String orderNo = outOrderDto.getOrderCode();
        if(StringUtils.isBlank(orderNo)){
            throw new BusinessException("单号不存在");
        }
        Integer count = outOrderMapper.selectCount(new QueryWrapper<OutOrder>().eq("order_code", orderNo));
        if(count>0){
            //处理单号，并重新插入缓存
            Integer number = outOrderMapper.selectCount(new QueryWrapper<OutOrder>().like("order_code", orderNo.substring(0,orderNo.length()-3)));
            OrderEnums.putCacheOrderNo(orderNo,number);
            throw new BusinessException("单号已存在，请重新下单");
        }else{
            OrderEnums.putCacheOrderNo(orderNo);
        }
        //插入主表
        OutOrder outOrder = new OutOrder();
        BeanUtils.copyBeanProp(outOrder, outOrderDto);
        int i = outOrderMapper.insert(outOrder);
        //批量插入子表
        for (OutOrderItem item : items) {
            item.setOutOrderId(outOrder.getId());
        }
        outOrderItemService.saveBatch(items);
        return i;
    }

    /**
     * 修改商品出库单主
     *
     * @param outOrderDto 出库单
     * @return 结果
     */
    @Override
    @Transactional
    public int updateOutOrder(OutOrderDto outOrderDto) {

        List<OutOrderItem> items = outOrderDto.getItems();
        if(CollectionUtils.isEmpty(items)){
            throw new BusinessException("子表不能为空");
        }
        //修改主表
        OutOrder outOrder = new OutOrder();
        BeanUtils.copyBeanProp(outOrder, outOrderDto);
        int i = outOrderMapper.updateById(outOrder);
        //获取子表
        List<OutOrderItem> outOrderItems = outOrderItemService.selectOutOrderItemListByMainId(outOrder.getId());
        if(!CollectionUtils.isEmpty(outOrderItems)) {
            List<Long> oldIds = outOrderItems.stream().map(OutOrderItem::getId).collect(Collectors.toList());
            List<Long> newIds = items.stream().map(OutOrderItem::getId).collect(Collectors.toList());
            oldIds.removeAll(newIds);
            if (!CollectionUtils.isEmpty(oldIds)) {
                //删除数据
                outOrderItemService.removeByIds(oldIds);
            }
        }
        for (OutOrderItem item : items) {
            if(null == item.getId()){
                item.setOutOrderId(outOrder.getId());
            }
            outOrderItemService.saveOrUpdate(item);

        }
        return i;
    }

    /**
     * 批量删除商品出库单主
     *
     * @param ids 需要删除的商品出库单主主键
     * @return 结果
     */
    @Override
    public int deleteOutOrderByIds(String ids) {
        int result = 0;
        Long[] mainIds = Convert.toLongArray(ids);
        for (Long id : mainIds ) {
            result =deleteOutOrderById(id);
            if(result <= 0){
                break;
            }
        }
        return result;
    }

    /**
     * 删除商品出库单主信息
     *
     * @param id 商品出库单主主键
     * @return 结果
     */
    @Override
    @Transactional
    public int deleteOutOrderById(Long id) {
        int result = 0;
        //更新主表
        int i=outOrderMapper.deleteById(id);
        //更新子表
        //查询子表信息
        List<OutOrderItem> outOrderItems = outOrderItemService.selectOutOrderItemListByMainId(id);
        if(!CollectionUtils.isEmpty(outOrderItems)) {
            List<Long> itemIds = outOrderItems.stream().map(OutOrderItem::getId).collect(Collectors.toList());
            Boolean flag = outOrderItemService.removeByIds(itemIds);
            if (i > 0 && flag) {
                result = 1;
            }
        }else{
            result=i;
        }
        return result;
    }

    @Override
    @Transactional
    public int checkStatus(CheckOrderLog checkOrderLog) {
        int result = 0;
        //获取入库数据
        Long id = checkOrderLog.getId();
        String orderStatus = checkOrderLog.getOrderStatus();
        OutOrder outOrder = outOrderMapper.selectById(id);
        if(CheckStatusEnums.OK_CHECK.getCode().equals(outOrder.getStatus())){
            throw new BusinessException("已审核，无须重复审核");
        }
        //添加审核信息
        CheckOrderLog log = new CheckOrderLog();
        log.setOrderType(OrderEnums.OUT_ORDER.getCode());
        log.setOrdeId(id);
        log.setOrderCode(outOrder.getOrderCode());
        log.setOrderStatus(orderStatus);
        log.setAdvice(checkOrderLog.getAdvice());
        log.setCreateBy(ShiroUtils.getLoginName());
        int i = checkOrderLogService.insertCheckOrderLog(log);
        //更新数据
        OutOrder upSetOutOrder = new OutOrder();
        upSetOutOrder.setId(id);
        upSetOutOrder.setStatus(orderStatus);
        int j = outOrderMapper.updateById(upSetOutOrder);
        if(!CheckStatusEnums.OK_CHECK.getCode().equals(orderStatus)){
            //驳回已完成
            return 1;
        }
        //回填上游单据
        String orderType = outOrder.getOrderType();
        Long sourceOrderId = outOrder.getSourceOrderId();

        //添加库存信息
        BigDecimal total=BigDecimal.ZERO;
        List<OutOrderItem> outOrderItems = outOrderItemService.selectOutOrderItemListByMainId(id);
        if(!CollectionUtils.isEmpty(outOrderItems)){
            StockOutLog stockOutLog = null;
            Stock stock = null;
            for (OutOrderItem outOrderItem : outOrderItems) {
                Date nowDate = DateUtils.getNowDate();
                //实际入库数量
                BigDecimal actualNumber = outOrderItem.getActualNumber()==null?BigDecimal.ZERO:outOrderItem.getActualNumber();
                //统计总数量
                total=total.add(actualNumber);
                //销售单
                if(OutOrderTypeEnums.SALE.getCode().equals(orderType) && null != sourceOrderId){
                    ErpSaleOrderItem item = new ErpSaleOrderItem();
                    item.setSaleOrderId(sourceOrderId);
                    item.setGoodsId(outOrderItem.getGoodsId());
                    List<ErpSaleOrderItem> items = saleOrderItemService.selectErpSaleOrderItemList(item);
                    if(!CollectionUtils.isEmpty(items)){
                        ErpSaleOrderItem erpSaleOrderItem = items.get(0);
                        ErpSaleOrderItem updateItem = new ErpSaleOrderItem();
                        updateItem.setId(erpSaleOrderItem.getId());
                        BigDecimal outNumber=actualNumber.add(erpSaleOrderItem.getOutNumber());
                        updateItem.setOutNumber(outNumber);
                        saleOrderItemService.updateById(updateItem);
                    }
                }
                //生产单领料单,不作处理
                if(OutOrderTypeEnums.APPLICATION.getCode().equals(orderType) && null != sourceOrderId){
                    ProductionOrderItem item = new ProductionOrderItem();
                    item.setMainId(sourceOrderId);
                    item.setGoodsId(outOrderItem.getGoodsId());
                    List<ProductionOrderItem> items = productionOrderItemService.selectProductionOrderItemList(item);
                    if(!CollectionUtils.isEmpty(items)){
                        ProductionOrderItem productionOrderItem = items.get(0);
                        ProductionOrderItem updateItem = new ProductionOrderItem();
                        updateItem.setId(productionOrderItem.getId());
                        BigDecimal outNumber = actualNumber.add(productionOrderItem.getOutNumber());
                        updateItem.setOutNumber(outNumber);
                        productionOrderItemService.updateById(updateItem);
                    }
                }
                //库存日志
                stockOutLog = new StockOutLog();
                stockOutLog.setBatchNo(outOrderItem.getBatchNo());
                stockOutLog.setOutType(outOrder.getOrderType());
                stockOutLog.setOrderId(id);
                stockOutLog.setOrderCode(outOrder.getOrderCode());
                stockOutLog.setGoodId(outOrderItem.getId());
                stockOutLog.setGoodCode(outOrderItem.getGoodsCode());
                stockOutLog.setGoodName(outOrderItem.getGoodsName());
                stockOutLog.setGoodUnit(outOrderItem.getGoodsUnit());
                stockOutLog.setGoodUnitDesc(outOrderItem.getGoodsUnitDesc());
                stockOutLog.setPackageUnit(outOrderItem.getPackageUnit());
                stockOutLog.setPackageNum(outOrderItem.getPackageNumber());
                stockOutLog.setWarehouseId(outOrder.getWarehouseId());
                stockOutLog.setWarehouseName(outOrder.getWarehouseName());
                stockOutLog.setCarriersId(outOrder.getCarriersId());
                stockOutLog.setCarriersName(outOrder.getCarriersName());
                stockOutLog.setCustomerId(outOrder.getCustomerId());
                stockOutLog.setCustomerName(outOrder.getCustomerName());
                stockOutLog.setOutNum(actualNumber);
                stockOutLog.setOutTime(nowDate);
                stockOutLog.setCreateBy(ShiroUtils.getLoginName());
                stockOutLog.setCreateTime(nowDate);
                //库存
                stock = new Stock();
                stock.setGoodsId(outOrderItem.getGoodsId());
                stock.setGoodsCode(outOrderItem.getGoodsCode());
                stock.setGoodsName(outOrderItem.getGoodsName());
                stock.setGoodsUnit(outOrderItem.getGoodsUnit());
                stock.setGoodsUnitDesc(outOrderItem.getGoodsUnitDesc());
                stock.setStockNumber(actualNumber);
                stock.setBatchNo(outOrderItem.getBatchNo());
                stock.setWarehouseId(outOrder.getWarehouseId());
                stock.setWarehouseName(outOrder.getWarehouseName());
                stockService.outStock(stock,stockOutLog);
            }
        }
        //回填主表
        //销售单
        if(OutOrderTypeEnums.SALE.getCode().equals(orderType) && null != sourceOrderId){
            ErpSaleOrder order = saleOrderService.getById(sourceOrderId);
            order.setDeliveryStatus(DeliverStatusEnums.OK_SEND.getCode());
            BigDecimal totalOutNumber = order.getOutNums().add(total);
            order.setOutNums(totalOutNumber);
            saleOrderService.updateById(order);
        }
        //领用单,
        if(OutOrderTypeEnums.APPLICATION.getCode().equals(orderType) && null != sourceOrderId){
            //主表状态进入由领料==》待生产
            ProductionOrder updatePrd = new ProductionOrder();
            updatePrd.setId(sourceOrderId);
            updatePrd.setProductStatus("1");//待生产
            productionOrderService.updateById(updatePrd);
        }
        if(i>0 && j>0){
            result =1;
        }
        return result;

    }

    @Override
    public OutOrderVo saleTransfor(Long id) {
        OutOrderVo outOrderVo = new OutOrderVo();
        if(null == id){
            return outOrderVo;
        }
        //1.获取销售单信息
        ErpSaleOrder saleOrder = saleOrderService.getById(id);
        if(null == saleOrder){
            return outOrderVo;
        }
        //2.组装数据

        //主表
        OutOrder outOrder = new OutOrder();
        outOrder.setOrderDate(new Date());
        outOrder.setOrderType(OutOrderTypeEnums.SALE.getCode());
        outOrder.setSourceOrderId(saleOrder.getId());
        outOrder.setSourceOrderCode(saleOrder.getOrderCode());
        outOrder.setCustomerId(saleOrder.getCustomerId());
        outOrder.setCustomerName(saleOrder.getCustomerName());
        outOrderVo.setOutOrder(outOrder);

        ArrayList<OutOrderItemVo> outOrderItemVos = new ArrayList<>();


        //子表,暂不处理，由前端选择仓库，重新加载
        outOrderVo.setItems(new ArrayList<OutOrderItemVo>());

        return outOrderVo;
    }

    @Override
    public OutOrderVo productTransfor(Long id) {
        OutOrderVo outOrderVo = new OutOrderVo();
        if(null == id){
            return outOrderVo;
        }
        //1.获取销售单信息
        ProductionOrder productionOrder = productionOrderService.getById(id);
        if(null == productionOrder){
            return outOrderVo;
        }
        //2.组装数据

        //主表
        OutOrder outOrder = new OutOrder();
        outOrder.setOrderDate(new Date());
        outOrder.setOrderType(OutOrderTypeEnums.APPLICATION.getCode());
        outOrder.setSourceOrderId(productionOrder.getId());
        outOrder.setSourceOrderCode(productionOrder.getOrderNo());
        outOrder.setCustomerId(productionOrder.getCustomerId());
        outOrder.setCustomerName(productionOrder.getCustomerName());
        outOrderVo.setOutOrder(outOrder);

        //子表,暂不处理，由前端选择仓库，重新加载
        outOrderVo.setItems(new ArrayList<OutOrderItemVo>());

        return outOrderVo;
    }


}
